package com.shiwaixiangcun.authz.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.FastJsonJsonView;
import com.shiwaixiangcun.authz.web.context.OAuthShiroHandlerExceptionResolver;
import com.shiwaixiangcun.core.CoreConstants;
import com.shiwaixiangcun.core.bind.method.annotation.*;
import org.springframework.context.annotation.*;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.json.MonkeyFastJsonView;

import java.util.*;

@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ComponentScan(
        basePackages = {"com.shiwaixiangcun.authz.web.controller","com.shiwaixiangcun.authz.*"},
        includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class, ControllerAdvice.class})}
)
public class WebConfig extends WebMvcConfigurerAdapter {

    /**
     * 对静态资源文件的访问 不支持访问WEB-INF目录
     **/
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        // 扩展名至mimeType的映射,即 /user.json => application/json
        configurer.favorPathExtension(true);
        //用于开启 /userinfo/123?format=json 的支持
        configurer.favorParameter(true);
        // <!-- 是否忽略Accept Header -->
        configurer.ignoreAcceptHeader(true);
        //<!--扩展名到MIME的映射；favorPathExtension, favorParameter是true时起作用  -->
        Map<String, MediaType> mediaTypes = new HashMap<>();
        mediaTypes.put("json", MediaType.APPLICATION_JSON_UTF8);
        mediaTypes.put("image",MediaType.IMAGE_JPEG);
        configurer.mediaTypes(mediaTypes);
        configurer.defaultContentType(MediaType.TEXT_HTML);
    }

    @Bean
    public ContentNegotiatingViewResolver viewResolver(ContentNegotiationManager contentNegotiationManager) {
        ContentNegotiatingViewResolver viewResolver = new ContentNegotiatingViewResolver();
        viewResolver.setOrder(0);
        viewResolver.setContentNegotiationManager(contentNegotiationManager);

        //配置视图解析器
        viewResolver.setViewResolvers(Collections.singletonList(htmlResourceViewResolver()));

        //<!-- 默认视图 放在解析链最后 -->
        viewResolver.setDefaultViews(Arrays.asList(fastJsonJsonView()));

        return viewResolver;
    }

    @Bean
    public InternalResourceViewResolver htmlResourceViewResolver() {
        InternalResourceViewResolver jspResolver = new InternalResourceViewResolver();
        jspResolver.setContentType("text/html");
        jspResolver.setPrefix("/");
        jspResolver.setSuffix(".jsp");
        return jspResolver;
    }


    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        commonsMultipartResolver.setDefaultEncoding(CoreConstants.ENCODING);
        commonsMultipartResolver.setMaxUploadSize(1024 * 1024 * 100L);
        commonsMultipartResolver.setMaxInMemorySize(40960);
        return commonsMultipartResolver;
    }

    @Bean
    public FastJsonJsonView fastJsonJsonView() {
        MonkeyFastJsonView jsonView = new MonkeyFastJsonView();
        jsonView.setFeatures(SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect);
        jsonView.setExtractValueFromSingleKeyModel(true);
        return jsonView;
    }


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new PageableMethodArgumentResolver());
        argumentResolvers.add(new MonkeyDtoMethodArgumentResolver());
        argumentResolvers.add(new FormModelMethodArgumentResolver());
    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        exceptionResolvers.add(new OAuthShiroHandlerExceptionResolver());
    }
}
